package com.javalsj.common.base.util;

import java.util.UUID;

import org.springframework.util.StringUtils;

/**
 * @description UUID生成工具类
 * @author WANGJIHONG
 * @date 2018年2月28日 下午8:35:30
 * @Copyright 版权所有 (c) www.javalsj.com
 * @memo 无备注信息
 */
public class UUIDUtils {

	private final static int h2b_A_10 = 'A' - 10;
	private final static int h2b_a_10 = 'a' - 10;
	/**
	 * 大写十六进制数组
	 */
	private final static char[] UPPER_HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	private static final UUID EMPTYUUID = UUID.fromString("00000000-0000-0000-0000-000000000000");

	public static UUID emptyUUID() {
		return EMPTYUUID;
	}

	public static boolean isEmpty(UUID uuid) {
		return uuid == null || EMPTYUUID.equals(uuid);
	}

	public static UUID newUUID() {
		return UUID.randomUUID();
	}

	public static UUID fromObject(Object id) {
		if (id == null || "".equals(id)) {
			return null;
		} else if (id instanceof UUID) {
			return (UUID) id;
		} else if (id instanceof byte[]) {
			return fromByte((byte[]) id);
		} else if (id instanceof String) {
			return fromString(String.valueOf(id));
		} else if (id instanceof Integer) {
			return new UUID(0, (int) id);
		}
		return null;
	}

	/**
	 * @param id
	 * @return 返回不带有中划线且全部大写32位字符串,如：38D4017797F14BBD9265B05BA6A0156F
	 */
	public static String toString(UUID id) {
		char[] charArray = new char[32];
		long least = id.getLeastSignificantBits();
		int index = 31;
		for (int i = 15; i >= 8; i--) {
			byte b = (byte) least;
			charArray[index--] = UUIDUtils.UPPER_HEX_DIGITS[b & 0xf];
			charArray[index--] = UUIDUtils.UPPER_HEX_DIGITS[b >>> 4 & 0xf];
			least >>>= 8;
		}
		long most = id.getMostSignificantBits();
		for (int i = 7; i >= 0; i--) {
			byte b = (byte) most;
			charArray[index--] = UUIDUtils.UPPER_HEX_DIGITS[b & 0xf];
			charArray[index--] = UUIDUtils.UPPER_HEX_DIGITS[b >>> 4 & 0xf];
			most >>>= 8;
		}
		return new String(charArray);
	}
	
	/**
	 * @param id
	 * @return 返回带有中划线的36位字符串,如： b007012b-767f-440d-95d3-fe69224e795d
	 */
	public static String toString36(UUID id) {
		return id.toString();
	}
 
	public static UUID fromByte(byte[] data) {
		if (data.length != 16) {
			throw new IllegalArgumentException("Invalid UUID byte[]");
		}

		long msb = 0;
		long lsb = 0;
		for (int i = 0; i < 8; i++)
			msb = (msb << 8) | (data[i] & 0xff);
		for (int i = 8; i < 16; i++)
			lsb = (lsb << 8) | (data[i] & 0xff);

		return new UUID(msb, lsb);
	}

	public static UUID fromString(String id) {
		if (StringUtils.isEmpty(id))
			return null;
		if (id.length() == 32) {
			return tryParse(id, false);
		} else if (id.length() == 36) {
			try {
				return UUID.fromString(id);
			} catch (Exception e) {
				return null;
			}
		} else {
			return null;
		}
	}

	public static String[] toString(UUID[] ids) {
		if (ids == null)
			return null;
		String[] result = new String[ids.length];
		for (int i = 0; i < ids.length; i++) {
			result[i] = ids[i].toString();
		}
		return result;
	}

	/**
	 * 返回UUID如果无效则返返回异常
	 */
	public static UUID valueOf(String str) {
		return tryParse(str, true);
	}

	public static UUID paserString(String id) {
		UUID uuid = fromString(id);
		if (uuid == null) {
			throw new IllegalArgumentException("UUID类型转化异常:"+id);
		}
		return uuid;
	}
	
	/**
	 * 根据两个long创建ID
	 *
	 * @param mostSigBits
	 *            高位
	 * @param leastSigBits
	 *            地位
	 * @return 返回ID
	 */
	public static UUID valueOf(final long mostSigBits, final long leastSigBits) {
		if (mostSigBits == 0 && leastSigBits == 0) {
			return EMPTYUUID;
		}
		return new UUID(mostSigBits, leastSigBits);
	}

	private static UUID tryParse(String str, boolean throwException) {
		if (str == null) {
			return null;
		}
		int strl = str.length();
		if (strl == 32) {
			try {
				return valueOf(hexToLong(str, 0), hexToLong(str, 16));
			} catch (RuntimeException e) {
				if (throwException) {
					throw e;
				}
			}
		}
		if (throwException) {
			throw new RuntimeException("UUID文本格式错误:" + str);
		}
		return null;
	}

	private static long hexToLong(String str, int start) {
		long temp = parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		temp = temp << 4 | parseChar(str, start++);
		return temp << 4 | parseChar(str, start++);
	}

	private static int parseChar(String s, int offset) throws RuntimeException, StringIndexOutOfBoundsException {
		char c = s.charAt(offset);
		if (c < '0') {
		} else if (c <= '9') {
			return c - '0';
		} else if (c < 'A') {
		} else if (c <= 'F') {
			return c - h2b_A_10;
		} else if (c < 'a') {
		} else if (c <= 'f') {
			return c - h2b_a_10;
		}
		throw new RuntimeException("在偏移量" + offset + "处出现无效的十六进制字符'" + c + "'");
	}


    public static UUID fromGuid(String guid) {
        if (StringUtils.isEmpty(guid)) {
            return UUID.fromString("00000000-0000-0000-0000-000000000000");
        }
        UUID uuid;
        if (guid.matches(".{8}-.{4}-.{4}-.{4}-.{12}")) {
            uuid = UUID.fromString(guid);
        } else if (guid.length() == 32) {
            StringBuffer uuidStr = new StringBuffer(64);
            uuidStr.append(guid.substring(0, 8)).append("-").append(guid.substring(8, 12)).append("-")
                    .append(guid.substring(12, 16)).append("-").append(guid.substring(16, 20)).append("-").append(guid.substring(20, guid.length()));
            uuid = UUID.fromString(uuidStr.toString());
            uuidStr.setLength(0);
            uuidStr = null;
        } else {
            System.out.println("guid=" + guid + "转换为UUID时失败");
            uuid = null;
        }
        return uuid;
    }

    public static String toGUID(UUID uuid){
        if(uuid == null || uuid.toString().equals("")){
            return "00000000000000000000000000000000";
        }
        String guid = uuid.toString().replaceAll("-","").toUpperCase();

        return guid;
    }

    public static UUID createEmptyUUID(){
        return UUID.fromString("00000000-0000-0000-0000-000000000000");
    }
	
}
